/***************************************************************************
*   Copyright (C) 2010-2011 by swkyer <swkyer@gmail.com>                  *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include "Jlink.h"
#include "Wiggler.h"
#include "JtagDev.h"


#ifdef _DEBUG
#pragma comment (lib, "../debug/jlinkusb.lib")
#else
#pragma comment (lib, "../release/jlinkusb.lib")
#endif


JTAGDEV_API jtagdev_t *jtagdev_open(jtagdev_cfg_t *pcfg)
{
    jtagdev_t *pjtag;

    if (pcfg == NULL)
    {
        fprintf(stderr, "error parameters.\n");
        return NULL;
    }

    pjtag = (jtagdev_t *)malloc(sizeof(jtagdev_t));
    if (pjtag == NULL)
    {
        fprintf(stderr, "faild to allocate memory, size: %d.\n", sizeof(jtagdev_t));
        return NULL;
    }
    memset(pjtag, 0, sizeof(jtagdev_t));

    switch (pcfg->devtype)
    {
    case JTAGDEV_TYPE_JLINK:
        pjtag->open = (void *(*)(jtagdev_cfg_t *))jlink_open;
        pjtag->close = (int (*)(void *))jlink_close;
        pjtag->reinit = (void *(*)(void *))jlink_reinit;

        pjtag->is_target_connect = (int (*)(void *))jlink_is_target_connect;
        pjtag->trst_activate = (int (*)(void *))jlink_trst_activate;
        pjtag->trst_deactivate = (int (*)(void *))jlink_trst_deactivate;
        pjtag->rst_activate = (int (*)(void *))jlink_rst_activate;
        pjtag->rst_deactivate = (int (*)(void *))jlink_rst_deactivate;

        pjtag->tap_reset = (int (*)(void *, int))jlink_tap_reset;
        pjtag->runtest_idle = (int (*)(void *))jlink_runtest_idle;

        pjtag->get_tap_state = (tap_state_t (*)(void *))jlink_get_tap_state;
        pjtag->tap_moveto = (int (*)(void *, tap_state_t))jlink_tap_moveto;

        pjtag->data = (int (*)(void *, ubase_t, ubase_t *))jlink_data;
        pjtag->instruction = (int (*)(void *, ubase_t, ubase_t *))jlink_instruction;
        break;
    case JTAGDEV_TYPE_WIGGLER:
        pjtag->open = (void *(*)(jtagdev_cfg_t *))wiggler_open;
        pjtag->close = (int (*)(void *))wiggler_close;
        pjtag->reinit = (void *(*)(void *))wiggler_reinit;

        pjtag->is_target_connect = (int (*)(void *))wiggler_is_target_connect;
        pjtag->trst_activate = (int (*)(void *))wiggler_trst_activate;
        pjtag->trst_deactivate = (int (*)(void *))wiggler_trst_deactivate;
        pjtag->rst_activate = (int (*)(void *))wiggler_rst_activate;
        pjtag->rst_deactivate = (int (*)(void *))wiggler_rst_deactivate;

        pjtag->tap_reset = (int (*)(void *, int))wiggler_tap_reset;
        pjtag->runtest_idle = (int (*)(void *))wiggler_runtest_idle;

        pjtag->get_tap_state = (tap_state_t (*)(void *))wiggler_get_tap_state;
        pjtag->tap_moveto = (int (*)(void *, tap_state_t))wiggler_tap_moveto;

        pjtag->data = (int (*)(void *, ubase_t, ubase_t *))wiggler_data;
        pjtag->instruction = (int (*)(void *, ubase_t, ubase_t *))wiggler_instruction;
        break;
    default:
        break;
    }

    pjtag->handle = pjtag->open(pcfg);
    if (pjtag->handle == NULL)
    {
        fprintf(stderr, "faild to open jtag device, type: %d, devnum: %d\n", pcfg->devtype, pcfg->devnum);
        free(pjtag);
        return NULL;
    }

    return pjtag;
}

JTAGDEV_API int jtagdev_close(jtagdev_t *pjtag)
{
    if (pjtag == NULL)
        return -1;

    if (pjtag->close)
        pjtag->close(pjtag->handle);
    free(pjtag);
    return 0;
}

JTAGDEV_API jtagdev_t *jtagdev_reinit(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->reinit)
        pjtag->handle = pjtag->reinit(pjtag->handle);
    return pjtag;
}

JTAGDEV_API int jtagdev_is_target_connect(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->is_target_connect)
        return pjtag->is_target_connect(pjtag->handle);
    return -1;
}

JTAGDEV_API int jtagdev_trst_activate(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->trst_activate)
        return pjtag->trst_activate(pjtag->handle);
    return -1;
}

JTAGDEV_API int jtagdev_trst_deactivate(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->trst_deactivate)
        return pjtag->trst_deactivate(pjtag->handle);
    return -1;
}

JTAGDEV_API int jtagdev_rst_activate(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->rst_activate)
        return pjtag->rst_activate(pjtag->handle);
    return -1;
}

JTAGDEV_API int jtagdev_rst_deactivate(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->rst_deactivate)
        return pjtag->rst_deactivate(pjtag->handle);
    return -1;
}

JTAGDEV_API int jtagdev_tap_reset(jtagdev_t *pjtag, int use_trst)
{
    if (pjtag && pjtag->tap_reset)
        return pjtag->tap_reset(pjtag->handle, use_trst);
    return -1;
}

JTAGDEV_API int jtagdev_runtest_idle(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->runtest_idle)
        return pjtag->runtest_idle(pjtag->handle);
    return -1;
}

JTAGDEV_API tap_state_t jtagdev_get_tap_state(jtagdev_t *pjtag)
{
    if (pjtag && pjtag->get_tap_state)
        return pjtag->get_tap_state(pjtag->handle);
    return TAP_INVALID;
}

JTAGDEV_API int jtagdev_tap_moveto(jtagdev_t *pjtag, tap_state_t dest)
{
    if (pjtag && pjtag->tap_moveto)
        return pjtag->tap_moveto(pjtag->handle, dest);
    return -1;
}

JTAGDEV_API int jtagdev_data(jtagdev_t *pjtag, ubase_t data_out, ubase_t *pdatain)
{
    if (pjtag && pjtag->data)
        return pjtag->data(pjtag->handle, data_out, pdatain);
    return -1;
}

JTAGDEV_API int jtagdev_instruction(jtagdev_t *pjtag, ubase_t ir_out, ubase_t *pirin)
{
    if (pjtag && pjtag->instruction)
        return pjtag->instruction(pjtag->handle, ir_out, pirin);
    return -1;
}
